package net.oschina.dajiangnan.tree;


import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TreeConfig {

    private static final Pattern patternNode = Pattern.compile("[a-zA-Z]+(_\\d)?\\s*\\[\\s*shape\\s*=\\s*(box|diamond)\\s*,");
    private static final Pattern getPatternFlow = Pattern.compile("[a-zA-Z]+(_\\d)?(\\s*->\\s*[a-zA-Z]+(_\\d)?)+");
    public interface DotLoader {
        String getContent() throws Exception;
    }

    /**
     * 一, 使用dot脚本构造流程的tree结构，解析的元素如下
     * 1. ->
     * 2. shape = diamond 和 shape = box (菱形和方块)
     * 二，约定
     * 1. 节点的名称使用类名
     * 2. 节点名称(类名) + 下划线 + 数字,表示相同的类的不同节点(对象)。即:流程中相同实现的不同节点
     * 三,使用Dot脚本生成图形(需安装http://www.graphviz.org/工具)
     * dot -Tpng index.dot -o index.png
     *
     * @param dotLoader         Dot脚本加载器
     * @param nodePackagePrefix 实现节点的package前缀
     * @return 流程头结点
     * @throws Exception
     */
    public AbstractNode getRootNode(DotLoader dotLoader, String nodePackagePrefix) throws Exception {
        String content = dotLoader.getContent();

        //正则节点定义
        Map<String, Object> nodePoolMap = new HashMap<>();
        Matcher matcher = patternNode.matcher(content);
        while (matcher.find()) {
            String nodeName = matcher.group().trim().split("\\[")[0];
            String className = nodeName.split("_")[0];
            nodePoolMap.put(nodeName, Class.forName(nodePackagePrefix + className).newInstance());
        }

        AbstractNode root = null;
        //正则流程定义
        matcher = getPatternFlow.matcher(content);
        while (matcher.find()) {
            String[] flows = matcher.group().split("->");
            for (int i = 0; i < flows.length; i++) {
                Object nodeObject = nodePoolMap.get(flows[i].trim());
                if (root == null) {
                    //tree的头结点
                    root = (AbstractNode) nodeObject;
                }
                if (i + 1 == flows.length) {
                    //dot一行定义的最后一个节点
                    continue;
                }
                if (nodeObject instanceof CommonNode) {
                    ((CommonNode) nodeObject).setNext((Node) nodePoolMap.get(flows[i + 1].trim()));
                }
                //按照脚本书写顺序定义左右节点,所以若左节点为null则为右节点
                if (nodeObject instanceof CrossNode) {
                    if (((CrossNode) nodeObject).getLeftNode() == null) {
                        ((CrossNode) nodeObject).setLeftNode((Node) nodePoolMap.get(flows[i + 1].trim()));
                    } else {
                        ((CrossNode) nodeObject).setRightNode((Node) nodePoolMap.get(flows[i + 1].trim()));
                    }
                }
            }
        }
        return root;
    }
}
